Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / meshchatx / src / backend / sticker_pack_utils.py

Displaying Raw • Download


meshchatx/src/backend/sticker_pack_utils.py a9cc4b996b8da8ff414e305825f372ca12dc138d (a9cc4b99) Text, 5.28 KB

T8b949e# SPDX-License-Identifier: 0BSD

T8b949e"""Validation and (de)serialization for MeshChatX sticker packs.

A sticker pack is a named collection of stickers. Packs use the
meshchatx-stickerpack JSON document format so they can be exported to a
local file, attached to an LXMF message for peer sharing, or installed back
into another identity's library.
"""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787base64

Te6edf3PACK_FORMAT Tff7b72= Ta5d6ff"Ta5d6ffmeshchatx-stickerpackTa5d6ff"
Te6edf3PACK_VERSION Tff7b72= T79c0ff1
Te6edf3PACK_FILENAME_SUFFIX Tff7b72= Ta5d6ff"Ta5d6ff.meshchatxpack.jsonTa5d6ff"

Te6edf3_VALID_PACK_TYPES Tff7b72= Tffa657frozensetTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffstaticTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffanimatedTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffvideoTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffmixedTa5d6ff"Tb4b4b4}Tb4b4b4)


Tff7b72def Td2a8ffsanitize_pack_titleTb4b4b4(Te6edf3titleTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Return a printable title for a pack, defaulting to "Untitled pack"."""
Tff7b72if Te6edf3title Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffUntitled packTa5d6ff"
Te6edf3s Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3ch Tff7b72for Te6edf3ch Tff7b72in Tffa657strTb4b4b4(Te6edf3titleTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72if Te6edf3chTff7b72.Td2a8ffisprintableTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72return Te6edf3sTb4b4b4[Tb4b4b4:T79c0ff80Tb4b4b4] Tff7b72if Te6edf3s Tff7b72else Ta5d6ff"Ta5d6ffUntitled packTa5d6ff"


Tff7b72def Td2a8ffsanitize_pack_short_nameTb4b4b4(Te6edf3nameTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Return a slug-compatible short name (alnum/underscore/dash) or None."""
Tff7b72if Te6edf3name Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Tffa657strTb4b4b4(Te6edf3nameTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Te6edf3out Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3ch Tff7b72for Te6edf3ch Tff7b72in Te6edf3s Tff7b72if Te6edf3chTff7b72.Td2a8ffisalnumTb4b4b4(Tb4b4b4) Tff7b72or Te6edf3ch Tff7b72in Tb4b4b4{Ta5d6ff"Ta5d6ff_Ta5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ff-Ta5d6ff"Tb4b4b4}Tb4b4b4)
Tff7b72return Te6edf3outTb4b4b4[Tb4b4b4:T79c0ff32Tb4b4b4] Tff7b72if Te6edf3out Tff7b72else Tff7b72None


Tff7b72def Td2a8ffsanitize_pack_descriptionTb4b4b4(Te6edf3descriptionTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Trim and clamp the optional pack description to 280 characters."""
Tff7b72if Te6edf3description Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72None
Te6edf3s Tff7b72= Ta5d6ff"Ta5d6ff"Tff7b72.Td2a8ffjoinTb4b4b4(Te6edf3ch Tff7b72for Te6edf3ch Tff7b72in Tffa657strTb4b4b4(Te6edf3descriptionTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4) Tff7b72if Te6edf3chTff7b72.Td2a8ffisprintableTb4b4b4(Tb4b4b4) Tff7b72or Te6edf3ch Tff7b72== Ta5d6ff"Tffea00\nTa5d6ff"Tb4b4b4)
Tff7b72return Te6edf3sTb4b4b4[Tb4b4b4:T79c0ff280Tb4b4b4] Tff7b72if Te6edf3s Tff7b72else Tff7b72None


Tff7b72def Td2a8ffsanitize_pack_typeTb4b4b4(Te6edf3pack_typeTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Normalize a pack type to one of static|animated|video|mixed."""
Tff7b72if Tff7b72not Te6edf3pack_typeTb4b4b4:
Tff7b72return Ta5d6ff"Ta5d6ffmixedTa5d6ff"
Te6edf3s Tff7b72= Tffa657strTb4b4b4(Te6edf3pack_typeTb4b4b4)Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tff7b72.Td2a8fflowerTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3s Tff7b72if Te6edf3s Tff7b72in Te6edf3_VALID_PACK_TYPES Tff7b72else Ta5d6ff"Ta5d6ffmixedTa5d6ff"


Tff7b72def Td2a8ffbuild_pack_documentTb4b4b4(
Te6edf3packTb4b4b4: Tffa657dictTb4b4b4,
Te6edf3stickersTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4,
Te6edf3exported_at_isoTb4b4b4: Tffa657strTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Build a meshchatx-stickerpack document from a pack and its stickers.

pack is a row from user_sticker_packs. stickers is a list of
rows containing name, emoji, image_type, image_bytes (base64
string), and optional metadata fields.
"""
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffformatTa5d6ff"Tb4b4b4: Te6edf3PACK_FORMATTb4b4b4,
Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4: Te6edf3PACK_VERSIONTb4b4b4,
Ta5d6ff"Ta5d6ffexported_atTa5d6ff"Tb4b4b4: Te6edf3exported_at_isoTb4b4b4,
Ta5d6ff"Ta5d6ffpackTa5d6ff"Tb4b4b4: Tb4b4b4{
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_titleTb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffshort_nameTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_short_nameTb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffshort_nameTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_descriptionTb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_typeTb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpack_typeTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffauthorTa5d6ff"Tb4b4b4: Tb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffauthorTa5d6ff"Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4[Tb4b4b4:T79c0ff80Tb4b4b4] Tff7b72or Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffis_strictTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3packTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_strictTa5d6ff"Tb4b4b4, Tff7b72TrueTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Ta5d6ff"Ta5d6ffstickersTa5d6ff"Tb4b4b4: Te6edf3stickersTb4b4b4,
Tb4b4b4}


Tff7b72def Td2a8ffvalidate_pack_documentTb4b4b4(Te6edf3dataTb4b4b4: Tffa657objectTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Parse and validate a meshchatx-stickerpack document.

Returns a dict with normalized pack and stickers lists. Raises
ValueError with a short reason on invalid input.
"""
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3dataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_pack_documentTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72if Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffformatTa5d6ff"Tb4b4b4) Tff7b72!= Te6edf3PACK_FORMATTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_pack_formatTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3ver Tff7b72= Tffa657intTb4b4b4(Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6ffversionTa5d6ff"Tb4b4b4]Tb4b4b4)
Tff7b72except Tb4b4b4(Tf85149KeyErrorTb4b4b4, Tf85149TypeErrorTb4b4b4, Tf85149ValueErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffunsupported_pack_versionTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Tff7b72if Te6edf3ver Tff7b72!= Te6edf3PACK_VERSIONTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffunsupported_pack_versionTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3pack_meta Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpackTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3pack_metaTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_pack_metaTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3stickers Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffstickersTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3stickersTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffinvalid_pack_stickersTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3out_stickersTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3iTb4b4b4, Te6edf3item Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3stickersTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3itemTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffinvalid_pack_sticker_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Te6edf3b64 Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3b64Tb4b4b4, Tffa657strTb4b4b4) Tff7b72or Tff7b72not Te6edf3b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffmissing_pack_sticker_bytes_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Te6edf3b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4, Te6edf3validateTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4) Tff7b72as Te6edf3excTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffinvalid_pack_sticker_base64_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4) Tff7b72from T7ee787exc
Te6edf3out_stickersTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4) Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657strTb4b4b4) Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4: Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657strTb4b4b4)
Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytes_b64Ta5d6ff"Tb4b4b4: Te6edf3b64Tff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffpackTa5d6ff"Tb4b4b4: Tb4b4b4{
Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_titleTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftitleTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffshort_nameTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_short_nameTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffshort_nameTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_descriptionTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffdescriptionTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpack_typeTa5d6ff"Tb4b4b4: Te6edf3sanitize_pack_typeTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4)Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffauthorTa5d6ff"Tb4b4b4: Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffauthorTa5d6ff"Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffauthorTa5d6ff"Tb4b4b4)Tb4b4b4, Tffa657strTb4b4b4)
Tff7b72else Tff7b72NoneTb4b4b4,
Ta5d6ff"Ta5d6ffis_strictTa5d6ff"Tb4b4b4: Tffa657boolTb4b4b4(Te6edf3pack_metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_strictTa5d6ff"Tb4b4b4, Tff7b72TrueTb4b4b4)Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Ta5d6ff"Ta5d6ffstickersTa5d6ff"Tb4b4b4: Te6edf3out_stickersTb4b4b4,
Tb4b4b4}


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────